package com.stb.client.dialog;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;

public abstract class AbstractDialogBox extends DialogBox {

	private final Button okButton = new Button("OK");
	private final Button cancelButton = new Button("Cancel");
	private final FlexTable mainPanel = new FlexTable();
	private final Set<TextBox> textBoxes = new HashSet<TextBox>();
	private final Label error = new Label();

	private final KeyUpHandler okCancelButtonHandler = new KeyUpHandler() {
		@Override
		public void onKeyUp(KeyUpEvent event) {
            if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER && okButton.isEnabled()) {
                okButton.click();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
                cancelButton.click();
            } 
            enableDisableControls();
		}
	};

	protected AbstractDialogBox(String title) {
		this.setText(title);
	    this.setAnimationEnabled(true);
		this.setWidget(this.mainPanel);
	}
	
	@Override
	public void show() 
	{
		this.initialise();
		super.show();
		this.center();
		this.setFocus();
	}

	/**
	 * Add all the dialog items and the OK and cancel buttons
	 */
	private void initialise() 
	{
		int row = 0;
		for (DialogItem item : this.getDialogItems()) {
		    TextBox textBox = item.getTextBox();
			this.textBoxes.add(textBox);
			this.mainPanel.setWidget(row, 0, new Label(item.getLabelText()));
		    this.mainPanel.setWidget(row, 1, textBox);
		    row++;
		    
		    // Add key up handler to catch escape and enter
		    textBox.addKeyUpHandler(this.okCancelButtonHandler);
		}

		this.mainPanel.setWidget(row++, 1, this.error);
		this.mainPanel.setWidget(row, 0, this.okButton);
		this.mainPanel.setWidget(row, 2, this.cancelButton);

		this.okButton.addKeyUpHandler(this.okCancelButtonHandler);
		this.okButton.setEnabled(false);
		this.okButton.addClickHandler(this.getOKHandler());

		this.cancelButton.addKeyUpHandler(this.okCancelButtonHandler);
		this.cancelButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				hide();
			}
		});
	}

	protected abstract void setFocus();
	protected abstract List<DialogItem> getDialogItems();
	protected abstract ClickHandler getOKHandler();

	private void enableDisableControls() {
        this.okButton.setEnabled(shouldEnableOk());
	}

	/**
	 * @return true if OK should be enabled
	 */
	protected boolean shouldEnableOk() {
        // Only enable OK button if all text boxes have text
        for (TextBox textBox : this.textBoxes) {
        	if (textBox.getText().length() == 0) {
        		return false;
        	}
        }
        return true;
	}

	protected void setError(String message) {
		this.error.setText(message);
		this.error.setStyleName("serverResponseLabelError");
	}
}
